import { Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Slider

A sliding input component that allows users to select a value within a specified range by dragging a handle or tapping on the track.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.widgets.slider/"/>
</LinkBadgeGroup>

## CLI

To generate and customize this style:

```shell copy
dart run forui style create slider
```

## Usage

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart copy
        FSlider(
          controller: FContinuousSliderController(
            selection: FSliderSelection(max: 0.6),
          ),
          initialSelection: FSliderSelection(max: 0.6),
        );
        ```
  </Tabs.Tab>
</Tabs>

### `FSlider(...)`

```dart copy
FSlider(
  style: FSliderStyle(...),
  layout: FLayout.rtl,
  tooltipBuilder: (style, value) => Text('${value.toStringAsFixed(2)}%'),
  controller: FContinuousSliderController(
    allowedInteraction: FSliderInteraction.tap,
    selection: FSliderSelection(max: 0.75, extent: (min: 0, max: 0.8)),
  ),
  onChange: (selection) {},
  marks: const [
    FSliderMark(value: 0, label: Text('0%')),
    FSliderMark(value: 0.5, label: Text('50%')),
    FSliderMark(value: 1, label: Text('100%')),
  ],
);
```

## Examples

### Appearance

#### Labelled

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{label: 'Volume', description: 'Adjust the volume by dragging the slider.'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {2-3} copy
        FSlider(
          label: const Text('Volume'),
          description: const Text('Adjust the volume by dragging the slider.'),
          controller: FContinuousSliderController(selection: FSliderSelection(max: 0.6)),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Disabled

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{enabled: 'false', label: 'Volume', description: 'Adjust the volume by dragging the slider.'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {7} copy
        FSlider(
          label: const Text('Volume'),
          description: const Text('Adjust the volume by dragging the slider.'),
          controller: FContinuousSliderController(
            selection: FSliderSelection(max: 0.6),
          ),
          enabled: false,
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Error

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{label: 'Volume', description: 'Adjust the volume by dragging the slider.', error: 'Volume is too high.'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {4} copy
        FSlider(
          label: const Text('Volume'),
          description: const Text('Adjust the volume by dragging the slider.'),
          forceErrorText: 'Volume is too high.',
          controller: FContinuousSliderController(selection: FSliderSelection(max: 0.6)),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Tooltip

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='tooltip'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {2-5} copy
        FSlider(
          tooltipBuilder: (style, value) {
            final hex = (value * 100).round().toRadixString(16).padLeft(2, '0');
            return Text('0x$hex');
          },
          controller: FContinuousSliderController(selection: FSliderSelection(max: 0.6)),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Marks

Marks provide visual reference points on the slider track. Each mark consists of:

- A tick: A visual indicator showing the mark's position
- A label: Text describing the mark's value (optional)

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='marks'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {4-8} copy
        FSlider(
          controller: FContinuousSliderController(selection: FSliderSelection(max: 0.35)),
          marks: const [
            FSliderMark(value: 0, label: Text('0%')),
            FSliderMark(value: 0.25, tick: false),
            FSliderMark(value: 0.5),
            FSliderMark(value: 0.75, tick: false),
            FSliderMark(value: 1, label: Text('100%')),
          ],
        );
        ```
  </Tabs.Tab>
</Tabs>

### Layouts and Selections

#### Discrete Values

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='discrete'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {4-8} copy
        FSlider(
          controller: FDiscreteSliderController(selection: FSliderSelection(max: 0.25)),
          marks: const [
            FSliderMark(value: 0, label: Text('0%')),
            FSliderMark(value: 0.25, tick: false),
            FSliderMark(value: 0.5),
            FSliderMark(value: 0.75, tick: false),
            FSliderMark(value: 1, label: Text('100%')),
          ],
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Range Selection

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='range'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {2-4} copy
        FSlider(
          controller: FContinuousSliderController.range(
            selection: FSliderSelection(min: 0.25, max: 0.75),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Selection Boundaries

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{extent: 'true'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {5} copy
        FSlider(
          controller: FContinuousSliderController(
            selection: FSliderSelection(
              max: 0.6,
              extent: (min: 0.25, max: 0.75),
            ),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Vertical Orientation

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='vertical' height={500}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {4} copy
        FSlider(
          label: const Text('Volume'),
          description: const Text('Adjust the volume by dragging the slider.'),
          layout: FLayout.btt,
          controller: FContinuousSliderController(selection: FSliderSelection(max: 0.35)),
          trackMainAxisExtent: 350,
          marks: const [
            FSliderMark(value: 0, label: Text('0%')),
            FSliderMark(value: 0.25, tick: false),
            FSliderMark(value: 0.5, label: Text('50%')),
            FSliderMark(value: 0.75, tick: false),
            FSliderMark(value: 1, label: Text('100%')),
          ],
        );
        ```
  </Tabs.Tab>
</Tabs>

### Interactions

#### Slide Track

Slide anywhere on the track or thumb to select a value.

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{interaction: 'slide'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {3} copy
        FSlider(
          controller: FContinuousSliderController(
            allowedInteraction: FSliderInteraction.slide,
            selection: FSliderSelection(max: 0.6),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Slide Thumb

Slide the thumb to select a value.

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{interaction: 'slideThumb'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {3} copy
        FSlider(
          controller: FContinuousSliderController(
            allowedInteraction: FSliderInteraction.slideThumb,
            selection: FSliderSelection(max: 0.6),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Tap

Tap anywhere on the track to select a value.

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{interaction: 'tap'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {3} copy
        FSlider(
          controller: FContinuousSliderController(
            allowedInteraction: FSliderInteraction.tap,
            selection: FSliderSelection(max: 0.6),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

#### Tap and Slide Thumb

Tap anywhere or slide the thumb to select a value.

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' query={{interaction: 'tapAndSlideThumb'}}/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart {3} copy
        FSlider(
          controller: FContinuousSliderController(
            allowedInteraction: FSliderInteraction.tapAndSlideThumb,
            selection: FSliderSelection(max: 0.6),
          ),
        );
        ```
  </Tabs.Tab>
</Tabs>

### Form

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='slider' variant='form' height='500'/>
  </Tabs.Tab>
  <Tabs.Tab>
        ```dart copy
        class SliderForm extends StatefulWidget {
          const SliderForm({super.key});

          @override
          State<SliderForm> createState() => SliderFormState();
        }

        class SliderFormState extends State<SliderForm> {
          final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

          @override
          Widget build(BuildContext context) => Form(
                key: _formKey,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    FSlider(
                      label: const Text('Brightness'),
                      description: const Text('Adjust the brightness level.'),
                      controller: FContinuousSliderController(selection: FSliderSelection(max: 0.35)),
                      marks: const [
                        FSliderMark(value: 0, label: Text('0%')),
                        FSliderMark(value: 0.25, tick: false),
                        FSliderMark(value: 0.5, label: Text('50%')),
                        FSliderMark(value: 0.75, tick: false),
                        FSliderMark(value: 1, label: Text('100%')),
                      ],
                    ),
                    const SizedBox(height: 20),
                    FButton(
                      child: const Text('Save'),
                      onPress: () {
                        if (!_formKey.currentState!.validate()) {
                          // Handle errors here.
                          return;
                        }

                        _formKey.currentState!.save();
                        // Do something.
                      },
                    ),
                  ],
                ),
              );
        }
        ```

  </Tabs.Tab>
</Tabs>
